package com.dudy.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * @program: zhuguangDemo
 * @description: 引导服务，bootStrap分层思想
 * @author: dudy
 * @create: 2018-04-12 00:53
 **/
public class EcoServer {
    private static final Logger logger = LoggerFactory.getLogger(EcoServer.class);
    private int port;

    public EcoServer(int port) {
        this.port = port;
    }

    /**
     * 引导服务启动
     *
     * @throws Exception
     */
    public void start() throws Exception {
        final EcoServerHandler ecoServerHandler = new EcoServerHandler();
        //线程池组，接受IO连接、读、写请求，一般为boss，work2个线程
        NioEventLoopGroup group = new NioEventLoopGroup();

        //辅助引导服务启动类
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            //将线程池组构建进来
            bootstrap.group(group).
                    //指定NIO的传输类型，使用NIO的高速通道
                            channel(NioServerSocketChannel.class).
                    //使用指定的端口设置套接字
                            localAddress(new InetSocketAddress(port)).
                    //添加一个EcoServerHandler到子Channel的ChannelPipeline
                            childHandler(new ChannelInitializer<SocketChannel>() {
                        //对每一个Channel进行初始化，形成职责连pipeline
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //自定义编码协议
    //                        MessageToByteEncoder、ByteToMessageDecoder
                            //构建pipeline，会挂很多实际的处理对象
                            ch.pipeline().addLast((ChannelHandler) ecoServerHandler);
                        }
                    });
            //异步绑定服务器，调用sync方法阻塞等待直接绑定完成
            ChannelFuture future = bootstrap.bind().sync();
            logger.info(EcoServer.class.getName() + " start listening " + future.channel().localAddress());
            //获取channel的closeFuture，关闭，并且阻塞当前线程直到他完成
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //关闭EventLoopGroup释放所有资源
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) {
        int port = 8888;
        try {
            new EcoServer(port).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
